/*
 * ============================================================================
 *
 *  Original modified Rotoblin module
 *
 *  File:			limithuntingrifle
 *  Type:			Module
 *  Description:	Adds a limit to hunting rifles for the survivors.
 *
 *  Copyright (C) 2012-2013  raziEiL <war4291@mail.ru>
 *  Copyright (C) 2010  Mr. Zero <mrzerodk@gmail.com
 *
 *  Rotoblin is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  Rotoblin is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with Rotoblin.  If not, see <http://www.gnu.org/licenses/>.
 *
 * ============================================================================
 */

/*
 * ==================================================
 *                     Variables
 * ==================================================
 */

/*
 * --------------------
 *       Private
 * --------------------
 */

static	const	Float:	TIP_TIMEOUT						= 8.0;
static			bool:	g_bHaveTipped[MAXPLAYERS + 1];


#define WEAPINDEX_PUMP			0
#define	WEAPINDEX_SMG			1
#define	WEAPINDEX_SNIPER		2
#define WEAPONS					3

static const String:g_sWeapon[WEAPONS][] =
{
	"weapon_pumpshotgun",
	"weapon_smg",
	"weapon_hunting_rifle"
};

static const String:g_sWeaponName[WEAPONS][] =
{
	"Pump shotgun",
	"SMG",
	"Hunting rifle"
};

static Handle:g_hLimit[WEAPONS], g_iCvarLimit[WEAPONS];

/**
 * Called on plugin start.
 *
 * @noreturn
 */
_LimitHuntingRifl_OnPluginStart()
{
	g_hLimit[WEAPINDEX_PUMP]		= CreateConVarEx("limit_pumpshotgun",	"-1", "Maximum of Pump shotguns the survivors can pick up.",	_, true, -1.0);
	g_hLimit[WEAPINDEX_SMG]		= CreateConVarEx("limit_submachinegun", "-1", "Maximum of SMG's the survivors can pick up.",			_, true, -1.0);
	g_hLimit[WEAPINDEX_SNIPER]	= CreateConVarEx("limit_huntingrifle",	"-1", "Maximum of Hunting rifles the survivors can pick up.",	_, true, -1.0);
}

/**
 * Called on plugin enabled.
 *
 * @noreturn
 */
_LHR_OnPluginEnabled()
{
	HookConVarChange(g_hLimit[WEAPINDEX_PUMP],		_LHR_OnCvarChange_LimitDualPistols);
	HookConVarChange(g_hLimit[WEAPINDEX_SMG],			_LHR_OnCvarChange_LimitSubmachineGuns);
	HookConVarChange(g_hLimit[WEAPINDEX_SNIPER], 	_LHR_OnCvarChange_LimitHuntingRifles);
	_LHR_GetCvars();

	for (new client = 1; client <= MaxClients; client++)
	{
		if (!IsClientInGame(client)) continue;
		SDKHook(client, SDKHook_WeaponCanUse, _LHR_SDKh_OnWeaponCanUse);
	}
}

/**
 * Called on plugin disabled.
 *
 * @noreturn
 */
_LHR_OnPluginDisabled()
{
	UnhookConVarChange(g_hLimit[WEAPINDEX_PUMP],			_LHR_OnCvarChange_LimitDualPistols);
	UnhookConVarChange(g_hLimit[WEAPINDEX_SMG],			_LHR_OnCvarChange_LimitSubmachineGuns);
	UnhookConVarChange(g_hLimit[WEAPINDEX_SNIPER], 		_LHR_OnCvarChange_LimitHuntingRifles);

	for (new client = 1; client <= MaxClients; client++)
	{
		if (!IsClientInGame(client)) continue;
		SDKUnhook(client, SDKHook_WeaponCanUse, _LHR_SDKh_OnWeaponCanUse);
	}
}

/**
 * Called on client put in server.
 *
 * @param client		Client index.
 * @noreturn
 */
_LHR_OnClientPutInServer(client)
{
	SDKHook(client, SDKHook_WeaponCanUse, _LHR_SDKh_OnWeaponCanUse);
}


/**
 * Called on weapon can use.
 *
 * @param client		Client index.
 * @param weapon		Weapon entity index.
 * @return				Plugin_Continue to allow weapon usage, Plugin_Handled
 *						to disallow weapon usage.
 */
public Action:_LHR_SDKh_OnWeaponCanUse(client, weapon)
{
	if (GetClientTeam(client) != TEAM_SURVIVOR) return Plugin_Continue;

	decl iWeap;
	if ((iWeap = WeapIDtoIndex(weapon)) == NULL || g_iCvarLimit[iWeap] == NULL) return Plugin_Continue;

	if ((iWeap == WEAPINDEX_SNIPER && IsFakeClient(client))) return Plugin_Handled;

	decl icurWeapon;
	if ((icurWeapon = GetPlayerWeaponSlot(client, 0)) != NULL && IsValidEntity(icurWeapon)){

		decl String:sClassName[64];
		GetEntityClassname(icurWeapon, sClassName, 64);

		// Survivor already got a weapon and trying to pick up a ammo refill, allow it
		if (StrEqual(sClassName, g_sWeapon[iWeap])) return Plugin_Continue;
	}

	if (g_bBlackSpot) return Plugin_Handled;

	if (GetActiveWeap(g_sWeapon[iWeap]) >= g_iCvarLimit[iWeap]) // If ammount of active weapons are at the limit
	{
		if (!IsFakeClient(client) && !g_bHaveTipped[client])
		{
			g_bHaveTipped[client] = true;

			if (g_iCvarLimit[iWeap] > 0)
				PrintToChat(client, "%s %s weapon group has reached its max of %d", MAIN_TAG, g_sWeaponName[iWeap], g_iCvarLimit[iWeap]);
			else
				PrintToChat(client, "%s %s is not allowed.", MAIN_TAG, g_sWeaponName[iWeap]);

			CreateTimer(TIP_TIMEOUT, _LHR_Tip_Timer, client);
		}
		return Plugin_Handled; // Dont allow survivor picking up the weapon
	}

	return Plugin_Continue;
}

public Action:_LHR_Tip_Timer(Handle:timer, any:client)
{
	g_bHaveTipped[client] = false;
}

static WeapIDtoIndex(iEnt)
{
	decl String:sClassName[64];
	GetEntityClassname(iEnt, sClassName, 64);

	for (new INDEX; INDEX < WEAPONS; INDEX++)
		if (StrEqual(sClassName, g_sWeapon[INDEX])) return INDEX;

	return NULL;
}

static GetActiveWeap(const String:sWeapClassName[])
{
	decl String:classname[64], weapon;
	new count;

	for (new i = 0; i < SurvivorCount; i++)
	{
		if (SurvivorIndex[i] <= 0 || !IsClientInGame(SurvivorIndex[i]) || !IsPlayerAlive(SurvivorIndex[i])) continue;

		if ((weapon = GetPlayerWeaponSlot(SurvivorIndex[i], 0)) == NULL || !IsValidEntity(weapon)) continue;

		GetEntityClassname(weapon, classname, 64);
		if (!StrEqual(classname, sWeapClassName)) continue;
		count++;
	}
	return count;
}

public _LHR_OnCvarChange_LimitDualPistols(Handle:convar, const String:oldValue[], const String:newValue[])
{
	g_iCvarLimit[WEAPINDEX_PUMP] = GetConVarInt(g_hLimit[WEAPINDEX_PUMP]);
}

public _LHR_OnCvarChange_LimitSubmachineGuns(Handle:convar, const String:oldValue[], const String:newValue[])
{
	g_iCvarLimit[WEAPINDEX_SMG] = GetConVarInt(g_hLimit[WEAPINDEX_SMG]);
}

public _LHR_OnCvarChange_LimitHuntingRifles(Handle:convar, const String:oldValue[], const String:newValue[])
{
	g_iCvarLimit[WEAPINDEX_SNIPER] = GetConVarInt(g_hLimit[WEAPINDEX_SNIPER]);
}

static _LHR_GetCvars()
{
	g_iCvarLimit[WEAPINDEX_PUMP] = GetConVarInt(g_hLimit[WEAPINDEX_PUMP]);
	g_iCvarLimit[WEAPINDEX_SMG] = GetConVarInt(g_hLimit[WEAPINDEX_SMG]);
	g_iCvarLimit[WEAPINDEX_SNIPER] = GetConVarInt(g_hLimit[WEAPINDEX_SNIPER]);
}

stock _LHR_CvarDump()
{
	decl iVal;
	if ((iVal = GetConVarInt(g_hLimit[WEAPINDEX_PUMP])) != g_iCvarLimit[WEAPINDEX_PUMP])
		DebugLog("%d		|	%d		|	rotoblin_limit_pumpshotgun", iVal, g_iCvarLimit[WEAPINDEX_PUMP]);
	if ((iVal = GetConVarInt(g_hLimit[WEAPINDEX_SMG])) != g_iCvarLimit[WEAPINDEX_SMG])
		DebugLog("%d		|	%d		|	rotoblin_limit_submachinegun", iVal, g_iCvarLimit[WEAPINDEX_SMG]);
	if ((iVal = GetConVarInt(g_hLimit[WEAPINDEX_SNIPER])) != g_iCvarLimit[WEAPINDEX_SNIPER])
		DebugLog("%d		|	%d		|	rotoblin_limit_huntingrifle", iVal, g_iCvarLimit[WEAPINDEX_SNIPER]);
}
